var fs = require('fs');
var parser = require('@babel/parser');
var traverse = require('@babel/traverse').default;
var t = require('@babel/types');
var generator = require('@babel/generator').default;
const { type } = require('os');

var jsCode = fs.readFileSync(`${__dirname}/encript.js`,{encoding:'utf-8'});
var chrome_vm = fs.readFileSync(`${__dirname}/var.js`,{encoding:'utf-8'});
eval(chrome_vm)
var ast = parser.parse(jsCode);
var ast2 = parser.parse(chrome_vm)
// traverse(ast,{
//     VariableDeclarator:delExtraName,
//     AssignmentExpression:delExtraName
// })
;
var var_names = [];
traverse(ast2,{
    VariableDeclarator:eval_func,
    AssignmentExpression:eval_func
})
;
traverse(ast,{
    Literal:normalLiteral
});
traverse(ast,{
    MemberExpression:keyToStr,
    CallExpression:keyToStr
});
traverse(ast,{
    Identifier:toVm
})
var code = chrome_vm + '\n' +  generator(ast,{compact:false}).code;
fs.writeFile(
    `${__dirname}/result.js`,code,
    (err)=>{
    }
)

// 变量的重命名===>VariableDeclartor/AssignmentExpression 且Identifier均不能再重新赋值
function delExtraName(path){
    var node = path.node;
    if(t.isVariableDeclarator(node)){
        if(!(t.isIdentifier(node.id)&&t.isIdentifier(node.init)))return;
            var localName = node.id.name;
            var binding = path.scope.getBinding(localName);
            if(!(binding&&binding.referenced))return;
            if(binding.constantViolations.length)return;
            var bindings = binding.referencePaths
            bindings.forEach(element => {
                element.replaceWith(node.init);
            });
            path.remove();

    }else if(t.isAssignmentExpression){
        if(!(t.isIdentifier(node.left)&&t.isIdentifier(node.right)))return;
        if(node.operator!='=')return;
            var globalName = node.left.name;
            var binding = path.scope.getBinding(globalName);
            if(!(binding&&binding.referenced))return;
            if(binding.constantViolations.length)return;
            var bindings = binding.referencePaths
            bindings.forEach(element => {
                element.replaceWith(node.init);
            });
            path.remove();
            debugger;

    }
}
;
function normalLiteral(path){
    delete path.node.extra;
}
;
// 获取环境名
function eval_func(path){
    var node = path.node;
    if(t.isVariableDeclarator(node)){
        var var_name = node.id.name;
        var_names.push(var_name)
    }else if(t.isAssignmentExpression){
        var var_name = node.left.name;
        var_names.push(var_name)
    }
}
// 解析环境
function keyToStr(path){
    var node = path.node;
    if(t.isFunctionDeclaration(path.parent)||t.isFunctionExpression(path.parent))return;
    if(t.isMemberExpression(node)){
        var name = node.object.name;
        if(var_names.indexOf(name)==-1)return;
        try{
            var res = eval(path.toString());
            if(typeof(res)=='undefined')return;
            path.replaceWith(t.valueToNode(res));
        }catch{
            return;
        }
    }else if(t.isCallExpression(node)){
        var name = node.callee.name;
        if(var_names.indexOf(name)==-1)return;
        try{
            var res = eval(path.toString());
            path.replaceWith(t.valueToNode(res));
        }catch{
            return;
        }
    }
};
function toVm(path){
    var node = path.node;
    var name = node.name;
    if(var_names.indexOf(name)==-1)return;
    if(Array.isArray(eval(name)))return;
    if(typeof(eval(name))=='function'){
        var value = eval(path.toString()).name;
        path.replaceWith(t.Identifier(value))
    }
    if((typeof(eval(name))=='string'||typeof(eval(name))=='number')){
        var value = eval(path.toString())
        path.replaceWith(t.valueToNode(value));
    }
    if(!(typeof(eval(name))=='object'))return;
    try{
        var value = eval(name).toString().replace(/\[|\]/g,'').split(' ')[1]
        path.replaceWith(t.Identifier(value))
    }catch{
        return;
    }
}